package com.music.service.Impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.music.mapper.SingleSongMapper;
import com.music.pojo.SingleSong;
import com.music.service.UserBasedCollaborativeFiltering;
import com.music.service.UserSimilarityCalculator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserBasedCollaborativeFilteringImpl implements UserBasedCollaborativeFiltering {
    @Autowired
    private UserSimilarityCalculator similarityCalculator;

    @Autowired
    private SingleSongMapper singleSongMapper;
    @Override
    public PageInfo<SingleSong> recommendMusicForUser(
            Map<Integer, Map<Integer, Integer>> userListeningHistory,
            Integer targetUserId,
            int numRecommendations,Integer pageNum) {

        // 存储用户相似度
        Map<Integer, Double> userSimilarities = new HashMap<>();

        // 计算目标用户与其他用户的相似度
        for (Integer userId : userListeningHistory.keySet()) {
            if (!userId.equals(targetUserId)) {
                double similarity = similarityCalculator.cosineSimilarity(
                        userListeningHistory.get(targetUserId),
                        userListeningHistory.get(userId));
                userSimilarities.put(userId, similarity);
            }
        }

        // 按相似度降序排序用户
        List<Integer> similarUsers = new ArrayList<>(userSimilarities.keySet());
        Collections.sort(similarUsers, (user1, user2) ->
                Double.compare(userSimilarities.get(user2), userSimilarities.get(user1)));

        // 生成推荐音乐列表
        List<Integer> recommendedMusicId = new ArrayList<>();
        Map<Integer, Integer> targetUserHistory = userListeningHistory.get(targetUserId);

        for (Integer user : similarUsers) {
            if (recommendedMusicId.size() >= numRecommendations) {
                break; // 已经有足够的推荐音乐
            }

            // 获取相似用户的听歌历史
            Map<Integer, Integer> similarUserHistory = userListeningHistory.get(user);

            // 找到相似用户听过而目标用户没有听过的音乐
            for (Integer musicId : similarUserHistory.keySet()) {
                if (!targetUserHistory.containsKey(musicId)) {
                    recommendedMusicId.add(musicId);
                    if (recommendedMusicId.size() >= numRecommendations) {
                        break; // 已经有足够的推荐音乐
                    }
                }
            }
        }
        /*
         * 首先将所有的SingleSong对象存储在all列表中。
         * 然后，它使用Java 8的流操作来过滤出那些音乐ID包含在recommendedMusicId列表中的音乐，
         * 并将它们收集到recommendedSingleSongs列表中。
         */
        List<SingleSong> all = singleSongMapper.findAll();
        List<SingleSong> recommendedSingleSongs = all.stream()
                .filter(singleSong -> recommendedMusicId.contains(singleSong.getMid()))
                .collect(Collectors.toList());

        PageHelper.startPage(pageNum,5);
        PageInfo<SingleSong> pageInfo = new PageInfo<>(recommendedSingleSongs);
        return pageInfo;
    }
}
